/*
 * SuffixAutomaton.cpp
 *
 *  Created on: 01-09-2013
 *      Author: Krzychu
 */

#include "SuffixAutomaton.h"

SuffixAutomaton::SuffixAutomaton(int vertexNumber, int edgeNumber) :
		Automaton(vertexNumber, edgeNumber)
{
	suffixLink = new int[vertexNumber];
	length = new int[vertexNumber];
	position = new int[vertexNumber];

	for (int i = 0; i < vertexNumber; i++)
	{
		suffixLink[i] = 0;
		length[i] = 0;
		position[i] = 0;
	}

	shift = new int[edgeNumber];

	for (int i = 0; i < edgeNumber; i++)
	{
		shift[i] = 0;
	}
}

SuffixAutomaton::~SuffixAutomaton()
{

}

int SuffixAutomaton::getSuffixLink(int vertex)
{
	int result = -1;

	if (vertex < vertexNumber && vertex > -1)
	{
		result = suffixLink[vertex];
	}

	return result;
}

void SuffixAutomaton::setSuffixLink(int vertex, int link)
{
	if (vertex < vertexNumber && vertex > -1)
	{
		suffixLink[vertex] = link;
	}
}

int SuffixAutomaton::getLength(int vertex)
{
	int result = -1;

	if (vertex < vertexNumber && vertex > -1)
	{
		result = length[vertex];
	}

	return result;
}

void SuffixAutomaton::setLength(int vertex, int length)
{
	if (vertex < vertexNumber && vertex > -1)
	{
		this->length[vertex] = length;
	}
}

int SuffixAutomaton::getPosition(int vertex)
{
	int result = -1;

	if (vertex < vertexNumber && vertex > -1)
	{
		result = position[vertex];
	}

	return result;
}

void SuffixAutomaton::setPosition(int vertex, int position)
{
	if (vertex < vertexNumber && vertex > -1)
	{
		this->position[vertex] = position;
	}
}

int SuffixAutomaton::getShift(int vertex, unsigned char label)
{
	int result = -1;

	if (vertex < vertexNumber && vertex * label < edgeNumber && vertex > -1)
	{
		result = shift[vertex * (edgeNumber / vertexNumber) + label];
	}

	return result;
}

void SuffixAutomaton::setShift(int vertex, unsigned char label, int shift)
{
	if (vertex < vertexNumber && vertex * label <= edgeNumber && vertex > -1)
	{
		this->shift[vertex * (edgeNumber / vertexNumber) + label] = shift;
	}
}

int SuffixAutomaton::addNode(int art, int node, char c)
{
	int childNode, suffixNode, suffixChildNode;

	childNode = newVertex();
	setTarget(node, c, childNode);
	suffixNode = getSuffixLink(node);
	if (suffixNode == art)
	{
		setSuffixLink(childNode, node);
	}
	else
	{
		suffixChildNode = getTarget(suffixNode, c);
		if (suffixChildNode == getUndefined())
		{
			suffixChildNode = addNode(art, suffixNode, c);
		}
		setSuffixLink(childNode, suffixChildNode);
	}
	return (childNode);
}
